🌴 🌴

USB Input Devices

& Tinkering with Digispark

A Guide to HID Emulation & Security

USB Device Basics

  1. Physical Detection: Voltage pull-up on D+ or D- signals a new connection.
  2. Reset & Default State: Host resets the bus; device responds at Default Address 0.
  3. Address Assignment: Host assigns a unique numeric address (1-127) to the device.
  4. Descriptor Exchange: Device sends its Vendor ID (VID) and Product ID (PID).
  5. Driver Matching: OS identifies device class (e.g., Mouse, Disk) and loads drivers.
  6. Ready State: Final configuration is set, and data transfer begins.

The USB HID Class

  • Describes "human interface devices" used with nearly every modern computer.
  • Utilizes predefined functions for universal software compatibility.
  • The same HID protocol is used unmodified in Bluetooth devices!

USB HID Keycodes

  • Standard codes covered in HID Usage Tables v1.7.
  • Codes 222-223 and 232-65535 are reserved.
  • Custom Actions: F13-F24, Execute, Help, Menu, Select, Media Controls.
  • Code 0 sends "no event", useful for keep-alive.
  • You can send delete presses to build a menu system.

Meet the Digispark

Combines a small breakout board (USB-A) with an Atmel (Microchip) ATTiny85 Microcontroller.

Digispark Pinout

ATTiny85 Specs

SpecValue
Input Voltage5V (USB)
Flash Memory8 KB (6 KB available for user code)
SRAM512 bytes (~400B available with USB libraries)
EEPROM512 bytes
Clock Speed16.5 MHz (internal oscillator)
Digital I/O Pins6 (all support PWM)
Analog Input Pins3

Example: The "Any-Key"

DOS Pause Prompt

A one-button device that emits a pseudo-random key press each time the button is pressed.

(Press down for source code)

Any-Key Code


/**
 * any key - press the push button and a random key is sent on the USB keyboard
 * requires a DigiSpark and a push button connecting PIN_BUTTON to GND
 */

#include "DigiKeyboard.h"

#define PIN_BUTTON 2
#define PIN_LED 1
#define DEBOUNCE_TIME 220

volatile bool isButtonPushed = false;
volatile static unsigned long lastPressedTime = 0;

void setup() {
  pinMode(PIN_BUTTON, INPUT_PULLUP);
  attachInterrupt(0, buttonPush, CHANGE);
  pinMode(PIN_LED, OUTPUT);
  digitalWrite(PIN_LED, LOW);
  DigiKeyboard.sendKeyStroke(0);
  DigiKeyboard.delay(250);
}

void loop() {
  if(isButtonPushed) {
    digitalWrite(PIN_LED, HIGH);
    DigiKeyboard.sendKeyStroke(random(4, 56));
    isButtonPushed = false;
    digitalWrite(PIN_LED, LOW);
  }
  DigiKeyboard.delay(5);
}

void buttonPush() {
  if (millis()-lastPressedTime > DEBOUNCE_TIME) {
    isButtonPushed = true;
    lastPressedTime = millis();
  }
}
                    

Example: Mouse Jiggler

Subtly moves the mouse pointer to prevent lock screens or annoy colleagues.

(Press down for source code)

Mouse Jiggler Code


// Digispark Mouse Jiggler
// Written by James Franklin for Air-Gap in 2019

#include <DigiMouse.h>
unsigned int LowerCycleTime = 10000;
unsigned int UpperCycleTime = 30000;

void setup() {
  randomSeed(analogRead(0));
  pinMode(1, OUTPUT);
  DigiMouse.begin();
}

void loop() {
  // Moves mouse 1 pixel in a direction (up/down/left/right) in a square
  digitalWrite(1, HIGH);
  DigiMouse.moveY(1);
  DigiMouse.delay(50);
  digitalWrite(1, LOW);
  DigiMouse.delay(random(LowerCycleTime, UpperCycleTime));

  // (Repeats for X(1), Y(-1), and X(-1) to complete the square)
}
                    

Emulating Other Devices

  • Mice: X and Y axis movements, scroll wheel & 3 buttons.
  • Joysticks: 6 analog axes & 16 buttons sent in one message.
  • CDC & Serial: Read raw sensor values via device redirection.

Tricky Areas & Gotchas

  • Keyboard Layouts: OS controls the layout — avoid location-sensitive keys (Y/Z, punctuation) or set the layout to match your setup.
  • Limited Memory: Use EEPROM / PROGMEM to store longer strings and read them byte-by-byte to save RAM.
  • Shared Pins: Pins 2 & 3 are used for the USB data lines.
  • Boot Delay: Bootloader waits ~5 seconds at startup for a new program.
  • Fuse Burning: Irreversible bypass of the loader to start app instantly.

USB & Security

  • "BadUSB" (2014): Highlighting the danger of programmable microcontrollers in harmless-looking devices.
  • USB Rubber Ducky: Commercial pen-testing device that rapidly executes keyboard payloads ("duck scripts").
  • Duck2Spark: Converts DuckEncoder payloads to Digispark Arduino sketches.

Demo Time!

  • Watch devices in action.
  • Pick your Digispark & inputs (buttons, rotary encoders).
  • Setup development environments (Arduino IDE / PlatformIO).
  • Soldering assistance available!